﻿using System;
using System.Diagnostics;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;

namespace TD.Interface
{
    /// <summary>
    /// Dummy sprite class.
    /// </summary>
    class Sprite
    {
        public Rectangle boundingRectangle { get; set; }
        public Point position { get; set; }
        public Texture2D texture { get; set; }
        public Rectangle[] current { get; set; }
        public int currentRect { get; set; }
    }

    /// <summary>
    /// Bits Per Pixel Collision Detection.
    /// </summary>
    class bppc
    {
        #region Bits Per Pixel Collision Detection
        /// <summary>
        /// W.I.P.
        /// </summary>
        /// <param name="a"></param>
        /// <param name="b"></param>
        /// <returns></returns>
        private bool bppCollission(Sprite a, Sprite b)
        {
            /**
             * PREREQUISITE: The sprites are overlapping! (IMPORTANT!!!)
             */

            // Now we create the overlapping rectangle. (This does not say anything about the textures yet!)
            Rectangle overlappingArea = GetOverlappingArea(a, b);

            Color[] colorsA = GetColorData(a);
            Color[] colorsB = GetColorData(b);

            // Only go over the parts that are overlapping each other!
            //   This is to prevent additional overhead.
            for (int y = 0; y < overlappingArea.Height; y++)
            {
                for (int x = 0; x < overlappingArea.Width; x++)
                {
                    // Grab the color of both sprites.
                    Color colorA = GetColor(a, ref colorsA, overlappingArea, y, x);
                    Color colorB = GetColor(b, ref colorsB, overlappingArea, y, x);

                    // Check if the alpha opacity is 50% or more.
                    if ((colorA.A & 0x80) > 0x00 && (colorB.A & 0x80) > 0)
                    {
                        Debug.WriteLine("Collide! (new)");
                        return true;
                    }
                }
            }

            return false;
        }

        /// <summary>
        /// Gets the overlapping area of both sprites.
        /// </summary>
        /// <param name="a"></param>
        /// <param name="b"></param>
        /// <returns>The overlapping area.</returns>
        private Rectangle GetOverlappingArea(Sprite a, Sprite b)
        {
            // Determine the left position of the overlapping area.
            int left = 0;
            {
                int lA = (int)(a.position.X);
                int lB = (int)(b.position.X);

                // Means B is our left line because B has the highest value.
                left = ((lA < lB) ? lB : lA);
            }

            // Determine the right position of the overlapping area.
            int right = 0;
            {
                int rA = (int)(a.position.X + a.boundingRectangle.Width);
                int rB = (int)(b.position.X + b.boundingRectangle.Width);

                // Means B is our right line because B has the lowest value.
                right = ((rA > rB) ? rB : rA);
            }

            // Determine the top position of the overlapping area.
            int top = 0;
            {
                int tA = (int)(a.position.Y);
                int tB = (int)(b.position.Y);

                // Means B is our top line because B has the highest value.
                top = ((tA < tB) ? tB : tA);
            }

            // Determine the bottom position of the overlapping area.
            int bottom = 0;
            {
                int bA = (int)(a.position.Y + a.boundingRectangle.Height);
                int bB = (int)(b.position.Y + b.boundingRectangle.Height);

                // Means B is our bottom line because B has the lowest value.
                bottom = ((bA > bB) ? bB : bA);
            }

            return new Rectangle(left, top, (right - left), (bottom - top));
        }

        /// <summary>
        /// Gets the color at the specified position within the overlapping area.
        /// </summary>
        /// <param name="sprite">The sprite from whom to get the color.</param>
        /// <param name="colors">The colors from the sprite.</param>
        /// <param name="overlappingArea">The area of overlapping.</param>
        /// <param name="y">The Y-offset in the overlapping area.</param>
        /// <param name="x">The X-offset in the overlapping area.</param>
        /// <returns>The color at the given position.</returns>
        private Color GetColor(Sprite sprite, ref Color[] colors, Rectangle overlappingArea, int y, int x)
        {
            // Gets absolute position within the visible rectangle.
            int x1 = GetRelativePosition(overlappingArea.X, (int)sprite.position.X);
            int y1 = GetRelativePosition(overlappingArea.Y, (int)sprite.position.Y);

            // Get the current rectangle. (Visible part of the texture.)
            Rectangle rect = sprite.current[sprite.currentRect];

            // Calculate the index of the color within the sprite.
            int idx = ((rect.Y + y1 + y) * rect.Width); // We are now on the appropriate line.
            idx += (rect.X + x1 + x); // We are now on the correct position within the visible rectangle.

            return colors[idx];
        }
        private int GetRelativePosition(int overlappingPos, int spritePos)
        {
            int value = 0x00;

            if (spritePos < overlappingPos)
            {
                value = (overlappingPos - spritePos);
                Debug.Assert(value >= 0x00);
            }
            else //if (spritePos >= overlappingPos) // Should only be == not >=
            {
                value = (spritePos - overlappingPos);
                Debug.Assert(value == 0x00);
            }

            return value;
        }

        /// <summary>
        /// Gets the color data of a sprite.
        /// </summary>
        /// <param name="sprite">The sprite from whom to get the color data.</param>
        /// <returns>The colors of the sprite in an array.</returns>
        private Color[] GetColorData(Sprite sprite)
        {
            Color[] colors = new Color[sprite.texture.Width * sprite.texture.Height];
            sprite.texture.GetData<Color>(colors);
            return colors;
        }
        #endregion
    }
}
